package com.ruanxie.handle;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruanxie.dto.classdetect.BaiduFaceSearchUserDTO;
import com.ruanxie.dto.classdetect.YoloResultDTO;
import com.ruanxie.entity.ClassDetectEntity;
import com.ruanxie.properties.BaiduApiPorperties;
import com.ruanxie.properties.CameraAndYoloProperties;
import com.ruanxie.utils.CameraCaputureUtil;
import com.ruanxie.utils.HttpClientUtil;
import com.ruanxie.utils.ImageUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;


//版本代码：src/main/java/com/wawu/testyolov5/handle/版本
//TODO 不适用于多线程环境，毕竟用的是电脑的摄像头只有一个
@Component
@Slf4j
public class CameraAndYoloWebSocketHandler implements org.springframework.web.socket.WebSocketHandler {
    private static final Map<String, WebSocketSession> SESSIONS = new ConcurrentHashMap<>();

    private static LocalDateTime detectBegin;
    private static LocalDateTime detectEnd;

    ScheduledExecutorService scheduledExecutorService;
    ScheduledFuture<?> scheduledFuture;
    ExecutorService yoloExecutor; // 用于异步执行 YOLOv5 任务
    //注意：不能在这里新建，否则线程池关闭后会导致该线程池不能再接受新的任务
//    关键点：
//    每次新连接时重新初始化线程池：通过在 afterConnectionEstablished 方法中重新创建 yoloExecutor，每次连接都能处理新的 YOLO 任务。
//    断开时优雅关闭线程池：在连接断开时，优雅关闭执行任务的线程池，防止资源泄露。

    //版本控制
    AtomicInteger versonCounter = new AtomicInteger(0);

    //TODO: 注意这里无法直接@Autowired
    static CameraCaputureUtil cameraCaputureUtil;
    static CameraAndYoloProperties cameraAndYoloProperties;
    @Autowired
    public void setCameraCaputureUtil(CameraCaputureUtil cameraCaputureUtil){
        CameraAndYoloWebSocketHandler.cameraCaputureUtil=cameraCaputureUtil;
    }
    @Autowired
    public void setCameraAndYoloProperties(CameraAndYoloProperties cameraAndYoloProperties){
        CameraAndYoloWebSocketHandler.cameraAndYoloProperties=cameraAndYoloProperties;
    }

    //识别的标签信息
    Map<String,List<String>> labelsMap =new ConcurrentHashMap<>();//这里直接存文件名了，否则太冗余了
    //文件名，对应的标签集

    //约定：一波，这里默认只有一张图片（这里主要为的是尽可能少更改python代码）
    /**
     * websocket连接建立后
     * （这里进行迭代开发，初版代码放在版本文件中）
     * @param session
     * @throws Exception
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("开启定时任务，进行yolov5识别..");
        //设置开始连接时间
        detectBegin=LocalDateTime.now();
        //创建线程池
        scheduledExecutorService = Executors.newScheduledThreadPool(1);//用于创建一个具有调度功能的线程池，也称为 调度线程池。
        //corePoolSize 参数指定了线程池的核心线程数，即至少保持活跃的线程数量
        //创建yolo异步运行线程
        yoloExecutor= Executors.newSingleThreadExecutor();

        //抓拍准备工作
        AtomicInteger counter = new AtomicInteger(0); // 定义一个计数器()//不能是普通的int，这个类型符合线程安全

        cameraCaputureUtil.start();


        //TODO TEST
//        cameraCaputureUtil.captureImage("222.jpg");

        // 开始定时拍照，每五秒进行一次
        scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
            int cnt=counter.getAndIncrement();
            //文件名:
//            DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH:mm:ss");
            String fileName= "V_"+versonCounter.get()+"captured_" + cnt + ".jpg";
            //保存图片
            String savePath = cameraAndYoloProperties.getCaptureImageDir() + fileName; // 使用计数器标记不同的图片
            String saveResultPath= cameraAndYoloProperties.getProjectOutputPath()+"/"+cameraAndYoloProperties.getDetectResultName()+"/"+fileName;

            cameraCaputureUtil.captureImage(savePath);
//            System.out.println(LocalDateTime.now());
            System.out.println("Captured image: " + savePath);

            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            Map<String,Object> result=new Hashtable<>();//定义返回结果
            result.put("time",LocalDateTime.now().format(dateTimeFormatter));
            result.put("saveResultPath",saveResultPath.replace(cameraAndYoloProperties.getProjectSaveStaticBaseLocation(),""));
//            result.put("fileName",fileName);//这个是一个冗余数据
            //yolo识别
            //TODO yolov5相当耗内存和时间，能否优化（感觉优化空间还是有的）
            // 这里主要是启动程序相当耗时间，可以试试能否一直启动（这里就需要去改python程序了）
            yoloExecutor.submit(()->{
                //命令：python C:\Users\wuyihan\Desktop\class_detect\yolov5\yolov5\detect.py --source C:\Users\wuyihan\Desktop\class_detect\yolov5\yolov5\test --weights C:\Users\wuyihan\Desktop\class_detect\yolov5\yolov5\weights\crowdhuman_vbody_yolov5m.pt --project C:\Users\wuyihan\Desktop\springboot-web-quickstart2\test-YOLOV5\yolo --name result --exist-ok
                //使用ProcessBuilder，需要的一个数组

                try {
                    YoloResultDTO yoloResultDTO;
                    if (cnt % 5 == 0) {
                        String[] command = CameraAndYoloProperties.getYoloRunPersonDetectCMD(savePath).split(" ");
//                    System.out.println(Arrays.toString(command));
                        yoloResultDTO = runYolo(command);
                        result.put("type",1);
                        //TODO 这里人数检测有坑呀，就是未单数时返回Vperson,复数为Vpersons
                        //  这里我直接在yoloResultDTO中硬编码了
//                        System.out.println(yoloResultDTO.getDetectResult());
                    } else {
                        String[] command = CameraAndYoloProperties.getYoloRunClassDetectCMD(savePath).split(" ");
//                    System.out.println(Arrays.toString(command));
                        yoloResultDTO = runYolo(command);

                        //这里还打算保存下标签信息，方便后续的人脸识别
                        List<String> labels = yoloResultDTO.getLabels();
                        if (!labels.isEmpty()){
                            labelsMap.put(fileName, labels);
                        }
                        result.put("type",2);
                    }

                    result.put("detectResult", yoloResultDTO.getDetectResult());
                    System.out.println(result);
                } catch (IOException | InterruptedException e) {
                    throw new RuntimeException(e);
                }
                //发送结果
                try {
                    session.sendMessage(new TextMessage(JSONObject.toJSONString(result)));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        }, 0, cameraAndYoloProperties.getCapturePeriod(), TimeUnit.SECONDS);//这里感觉可以把提取到配置文件种
    }


//构思：这里我运行yolo获取到一堆字符串，如何处理方便呢？
//    1.一开始想的使用流，过滤出image和label开头，但是感觉还是不够方便
//    2.后续打算约定一下，每次只识别一张图，把识别结果封装成类(一开始获取结果时，直接保存字符串，再通过这个处理获取到哪些想要的东西)

    /**
     * 运行yolo程序并获取结果（默认每次只识别一张）
     * @param command
     */
    private YoloResultDTO runYolo(String[] command) throws IOException, InterruptedException {


        // 使用 ProcessBuilder 构建并启动进程
        ProcessBuilder processBuilder = new ProcessBuilder(command);
        processBuilder.redirectErrorStream(true); // 将错误流和标准输出流合并
        Process process = processBuilder.start();

        // 等待进程结束
        int exitCode = process.waitFor();
        System.out.println("Process exited with code: " + exitCode);

        List<String> labels=new ArrayList<>();
        String result="";
        // 获取输出并打印
        BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//        String string = reader.lines().collect(Collectors.joining("\n")).toString();
//        System.out.println(string);
        String line;
        while ((line = reader.readLine()) != null) {
            //默认的yolo返回结果：
            //image 3/3 C:\Users\wuyihan\Desktop\springboot-web-quickstart2\test-YOLOV5\yolov5\test\zidane.jpg: 384x640 2 heads, 2 Vpersons,
            if (line.startsWith("image")) {
                result=line;
            } else if (line.startsWith("label")) {//傻了呀，这里拼错了
                labels.add(line);
            }
        }
//        // 等待进程结束
//        int exitCode = process.waitFor();
//        System.out.println("Process exited with code: " + exitCode);

        //设置返回结果
        return YoloResultDTO.builder()
                .labels(labels)
                .result(result).build();
    }

    @Override
    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {

    }

    //注意了：多线程环境下使用@Autowired会报错
    static BaiduApiPorperties baiduApiPorperties;
    @Autowired
    public void setBaiduApiPorperties(BaiduApiPorperties baiduApiPorperties){
        CameraAndYoloWebSocketHandler.baiduApiPorperties=baiduApiPorperties;
    }

    //TODO 待优化：职责太多了
    /**
     * 关闭连接的同时，调用百度人脸搜索api，映射到具体的人身上
     * @param session
     * @param closeStatus
     * @throws Exception
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
        log.info("关闭websocket连接...");
        //设置关闭时间
        detectEnd=LocalDateTime.now();
        // 1.取消定时任务
        if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
            scheduledFuture.cancel(true);
            System.out.println("task stopped.");
        }

        // 2.关闭定时任务线程池
        scheduledExecutorService.shutdown();
        try {
            if (!scheduledExecutorService.awaitTermination(1, TimeUnit.SECONDS)) {
                scheduledExecutorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            scheduledExecutorService.shutdownNow();
        }

        // 3.关闭YOLO执行线程池
        yoloExecutor.shutdown();
        try {
            if (!yoloExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
                yoloExecutor.shutdownNow();
            }
        } catch (InterruptedException e) {
            yoloExecutor.shutdownNow();
        }

        // 停止摄像头抓拍
        cameraCaputureUtil.stop();
        versonCounter.getAndIncrement();

        System.out.println("任务已经关闭");

        //处理标签信息，这里想着要映射到具体的人上
        Map<String,Map<Integer,Integer>> studentClassDetectCountMap =new HashMap<>();//key:studentId;value:{行为类别下标:出现次数}
        for (Map.Entry<String, List<String>> entry : labelsMap.entrySet()) {
            String fileName=entry.getKey();//文件名
            List<String> labels = entry.getValue();//当前文件对应的标签
            String savePath = cameraAndYoloProperties.getCaptureImageDir() + fileName;//对应的保存路径
            //当前当前文件所有的标签
            for(String label:labels){
                //标签格式："label: 类型下标 class x_center y_center width height"
                String[] s = label.split(" ");
                String base64Image = ImageUtil.imageSplitToBase64(savePath, Double.parseDouble(s[2]), Double.parseDouble(s[3]), Double.parseDouble(s[4]), Double.parseDouble(s[5]));
                Integer classIndex=Integer.valueOf(s[1]);
                //TODO 看看后续需不需要封装
                //TODO 优化：这里请求响应需要频繁的开启关闭还是有点消耗时间的
                //发送人脸搜索请求，获取到识别结果
                //////
                //设置Query参数，生成uri
                Map<String,String> uriParams=new HashMap<>();
//            uriParams.put("client_id",baiduApiPorperties.getAPIKey());
//            uriParams.put("client_secret",baiduApiPorperties.getSecretKey());
                uriParams.put("access_token",baiduApiPorperties.getAccessToken());
                URI uri = HttpClientUtil.buildUriWithParams("https://aip.baidubce.com/rest/2.0/face/v3/search", uriParams);
                //设置请求体信息
                Map<String,Object> jsonParams=new HashMap<>();
                jsonParams.put("group_id_list",baiduApiPorperties.getClassDetectionGroupIdList());
                jsonParams.put("image",base64Image);
                jsonParams.put("image_type","BASE64");
                String response = HttpClientUtil.doPost4Json(uri.toString(), jsonParams);
                System.out.println(response);
                //处理响应结果
                JSONObject result = JSON.parseObject(response).getJSONObject("result");
                if(result == null){
                    continue;
                }
                List<BaiduFaceSearchUserDTO> userList = result.getJSONArray("user_list").toJavaList(BaiduFaceSearchUserDTO.class);
                //这里只要第一个即可r
                //////

                //通过人脸搜索的结果，将yolo识别结果保存下来
                //记录学生的行为类别出现次数
                if(userList != null && !userList.isEmpty()){
                    //这里只获取到第一个识别结果
                    String studentId=userList.get(0).getUserId();
                    //获取到当前学生对应的当前课堂行为的出现次数，并更新
                    studentClassDetectCountMap.putIfAbsent(studentId,new HashMap<>());//如果当前值不存在插入这个
                    Map<Integer, Integer> classDetectCount = studentClassDetectCountMap.get(studentId);//这时候就能获取到这个值了
                    //注意获取到的是一个指针一个引用，能直接改变studentClassDetectCount中studentId对应的classDetectCount
                    //更新对应人的当前课堂行为的出现次数
                    classDetectCount.put(classIndex, classDetectCount.getOrDefault(classIndex,0)+1);
                }
            }
        }

        System.out.println(labelsMap);
        //转换成classDetect实体类
//        System.out.println(studentClassDetectCountMap);
        List<ClassDetectEntity> classDetectEntities = ClassDetectEntity.convertStudentClassDetectCountMapToEntities(studentClassDetectCountMap,detectBegin,detectEnd);
        System.out.println(classDetectEntities);
        //TODO 这里还没有存进数据库中

        //最后换下标签数组：
        labelsMap=new HashMap<>();
    }



    @Override
    public boolean supportsPartialMessages() {
        return false;
    }
}




//import com.alibaba.fastjson.JSONObject;
//import com.ruanxie.properties.CameraAndYoloProperties;
//import com.ruanxie.utils.CameraCaputureUtil;
//import lombok.extern.slf4j.Slf4j;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Component;
//import org.springframework.web.socket.CloseStatus;
//import org.springframework.web.socket.TextMessage;
//import org.springframework.web.socket.WebSocketMessage;
//import org.springframework.web.socket.WebSocketSession;
//
//import java.io.BufferedReader;
//import java.io.IOException;
//import java.io.InputStreamReader;
//import java.time.LocalDateTime;
//import java.time.format.DateTimeFormatter;
//import java.util.Arrays;
//import java.util.Hashtable;
//import java.util.Map;
//import java.util.concurrent.*;
//import java.util.concurrent.atomic.AtomicInteger;
//import java.util.regex.Matcher;
//import java.util.regex.Pattern;
//
////TODO 这里感觉不适用于多线程环境
//@Component
//@Slf4j
//public class CameraAndYoloWebSocketHandler implements org.springframework.web.socket.WebSocketHandler {
//    private static final Map<String, WebSocketSession> SESSIONS = new ConcurrentHashMap<>();
//
//    ScheduledExecutorService scheduledExecutorService;
//    ScheduledFuture<?> scheduledFuture;
//    ExecutorService yoloExecutor; // 用于异步执行 YOLOv5 任务
//        //注意：不能在这里新建，否则线程池关闭后会导致该线程池不能再接受新的任务
////    关键点：
////    每次新连接时重新初始化线程池：通过在 afterConnectionEstablished 方法中重新创建 yoloExecutor，每次连接都能处理新的 YOLO 任务。
////    断开时优雅关闭线程池：在连接断开时，优雅关闭执行任务的线程池，防止资源泄露。
//
//    //版本控制
//    AtomicInteger versonCounter = new AtomicInteger(0);
//
//    //TODO: 注意这里无法直接@Autowired
//    static CameraCaputureUtil cameraCaputureUtil;
//    static CameraAndYoloProperties cameraAndYoloProperties;
//    @Autowired
//    public void setCameraCaputureUtil(CameraCaputureUtil cameraCaputureUtil){
//        CameraAndYoloWebSocketHandler.cameraCaputureUtil=cameraCaputureUtil;
//    }
//    @Autowired
//    public void setCameraAndYoloProperties(CameraAndYoloProperties cameraAndYoloProperties){
//        CameraAndYoloWebSocketHandler.cameraAndYoloProperties=cameraAndYoloProperties;
//    }
//
//
//    @Override
//    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
//
//
//        //创建线程池
//        scheduledExecutorService = Executors.newScheduledThreadPool(1);//用于创建一个具有调度功能的线程池，也称为 调度线程池。
//            //corePoolSize 参数指定了线程池的核心线程数，即至少保持活跃的线程数量
//        //创建yolo异步运行线程
//        yoloExecutor= Executors.newSingleThreadExecutor();
//
//        //抓拍准备工作
//        AtomicInteger counter = new AtomicInteger(0); // 定义一个计数器()//不能是普通的int，这个类型符合线程安全
//
//        cameraCaputureUtil.start();
//
//
//        //TODO TEST
////        cameraCaputureUtil.captureImage("222.jpg");
//
//        // 开始定时拍照，每五秒进行一次
//        scheduledFuture = scheduledExecutorService.scheduleAtFixedRate(() -> {
//            int cnt=counter.getAndIncrement();
//            //文件名:
////            DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH:mm:ss");
//            String fileName= "V_"+versonCounter.get()+"captured_" + cnt + ".jpg";
//            //保存图片
//            String savePath = cameraAndYoloProperties.getCaptureImageDir() + fileName; // 使用计数器标记不同的图片
//            String saveResultPath= cameraAndYoloProperties.getProjectOutputPath()+"/"+cameraAndYoloProperties.getDetectResultName()+"/"+fileName;
//
//            cameraCaputureUtil.captureImage(savePath);
////            System.out.println(LocalDateTime.now());
//            System.out.println("Captured image: " + savePath);
//
//            DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//            Map<String,Object> result=new Hashtable<>();//定义返回结果
//            result.put("time",LocalDateTime.now().format(dateTimeFormatter));
//            result.put("saveResultPath",saveResultPath.replace(cameraAndYoloProperties.getProjectSaveStaticBaseLocation(),""));
//            //yolo识别
//            //TODO yolov5相当耗内存和时间，能否优化（感觉优化空间还是有的）
//            // 这里主要是启动程序相当耗时间，可以试试能否一直启动（这里就需要去改python程序了）
//            yoloExecutor.submit(()->{
//                //命令：python C:\Users\wuyihan\Desktop\class_detect\yolov5\yolov5\detect.py --source C:\Users\wuyihan\Desktop\class_detect\yolov5\yolov5\test --weights C:\Users\wuyihan\Desktop\class_detect\yolov5\yolov5\weights\crowdhuman_vbody_yolov5m.pt --project C:\Users\wuyihan\Desktop\springboot-web-quickstart2\test-YOLOV5\yolo --name result --exist-ok
////                String[] command = {
////                        "cmd.exe", "/c",
////                        "conda activate pytorch_test && " +
////                                "python yolov5/detect.py --source " + savePath +
////                                " --classes 1 --weights yolov5/weights/crowdhuman_vbody_yolov5m.pt " +
////                                "--project src/main/resources/static/images/yolo --name result --exist-ok "
////                };
//                //这里不知道为什么字符串不行
////                System.out.println(command);
////        String[] command=CameraAndYoloProperties.getYoloRunPersonDetectCMD(savePath).split(" ");//这里idea只能通过类名调静态方法
//                if (cnt % 5 == 0){
//                    String[] command = CameraAndYoloProperties.getYoloRunPersonDetectCMD(savePath).split(" ");
//                    System.out.println(Arrays.toString(command));
////                    result.put("type",1);//TODO 优化
//                    yoloDetect(session,command,result);
//                }else{
//                    String[] command = CameraAndYoloProperties.getYoloRunClassDetectCMD(savePath).split(" ");
//                    System.out.println(Arrays.toString(command));
////                    result.put("type",2);
//                    yoloDetect(session,command,result);
//                }
//            });
//        }, 0, cameraAndYoloProperties.getCapturePeriod(), TimeUnit.SECONDS);//这里感觉可以把提取到配置文件种
//    }
//
//    /**
//     * 进行进行yolo识别，同时通过websocket返回给前端识别后的数据
//     *      (这里将这部分代码抽取出来)
//     * @param session
//     * @param command
//     * @param result
//     */
//    private void yoloDetect(WebSocketSession session,String[] command,Map result){
//
//        try {
//            // 使用 ProcessBuilder 构建并启动进程
//            ProcessBuilder processBuilder = new ProcessBuilder(command);
//            processBuilder.redirectErrorStream(true); // 将错误流和标准输出流合并
//            Process process = processBuilder.start();
//
//            // 获取输出并打印
//            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
//            String line;
//
//            Map<String,Object> detectResult=new Hashtable<>();//检测的结果
//            // 定义匹配物体类型和数量的正则表达式
//            Pattern detectionPattern = Pattern.compile("(\\d+)\\s([a-zA-Z]+), ");
//            while ((line = reader.readLine()) != null) {
////                    System.out.println(line);//配置好后在注释掉
//                // 只处理以 "image" 开头的行
//                if (line.startsWith("image")) {
////                        System.out.println("Processing detection result: " + line);
//
//                    // 查找检测的类型和数量
//                    Matcher matcher = detectionPattern.matcher(line);
//                    while (matcher.find()) {
//                        // group(1) 是数量，group(2) 是类别
//                        Integer count =Integer.valueOf(matcher.group(1));
//                        String type = matcher.group(2);
//                        System.out.println("检测到 " + count + " 个 " + type);
//                        detectResult.put(type,count);
////                                session.sendMessage(new TextMessage("检测到 " + count + " 个 " + type));
//                    }
//                    result.put("detectResult",detectResult);
//                    session.sendMessage(new TextMessage(JSONObject.toJSONString(result)));
//                }
//            }
//
//            // 等待进程结束
//            int exitCode = process.waitFor();
//            System.out.println("Process exited with code: " + exitCode);
//
//        } catch (IOException | InterruptedException e) {
//            e.printStackTrace();
//        }
//
//    }
//
//    @Override
//    public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
//
//    }
//
//    @Override
//    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
//
//    }
//
//    @Override
//    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
//        // 1.取消定时任务
//        if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
//            scheduledFuture.cancel(true);
//            System.out.println("task stopped.");
//        }
//
//        // 2.关闭定时任务线程池
//        scheduledExecutorService.shutdown();
//        try {
//            if (!scheduledExecutorService.awaitTermination(1, TimeUnit.SECONDS)) {
//                scheduledExecutorService.shutdownNow();
//            }
//        } catch (InterruptedException e) {
//            scheduledExecutorService.shutdownNow();
//        }
//
//        // 3.关闭YOLO执行线程池
//        yoloExecutor.shutdown();
//        try {
//            if (!yoloExecutor.awaitTermination(1, TimeUnit.SECONDS)) {
//                yoloExecutor.shutdownNow();
//            }
//        } catch (InterruptedException e) {
//            yoloExecutor.shutdownNow();
//        }
//
//        // 停止摄像头抓拍
//        cameraCaputureUtil.stop();
//        versonCounter.getAndIncrement();
//
//        System.out.println("任务已经关闭");
//    }
//
//
//    @Override
//    public boolean supportsPartialMessages() {
//        return false;
//    }
//}
